import wave
import matplotlib.pyplot as plt
import numpy as np
import os

import keras
from keras.models import Sequential
from keras.layers import Dense

# 加载数据集 和 标签[并返回标签集的处理结果]
def create_datasets():
    wavs=[]
    labels=[] # labels 和 testlabels 这里面存的值都是对应标签的下标，下标对应的名字在labsInd中
    testwavs=[]
    testlabels=[]

    labsInd=[]      ## 训练集标签的名字   0：seven   1：stop
    testlabsInd=[]  ## 测试集标签的名字   0：seven   1：stop

    path=r'D:/Pycharm/trainvoice5/train/abnormal_treble/'
    files = os.listdir(path)
    for i in files:
        print(path+i)
        waveData = get_wav_mfcc(path+i)   #把每一条音频转换为mfcc形式
        # print(waveData)
        wavs.append(waveData)
        if ("3" in labsInd)==False:
            labsInd.append("3")
        labels.append(labsInd.index("3"))


    path=r'D:/Pycharm/trainvoice5/train/normal_bass/'
    files = os.listdir(path)
    for i in files:
        #print(i)
        waveData = get_wav_mfcc(path+i)
        wavs.append(waveData)
        if ("4" in labsInd)==False:
            labsInd.append("4")
        labels.append(labsInd.index("4"))

############################################

    path=r'D:/Pycharm/trainvoice5/test/abnormal_treble/'
    files = os.listdir(path)
    for i in files:
        # print(i)
        waveData = get_wav_mfcc(path+i)
        testwavs.append(waveData)
        if ("3" in testlabsInd)==False:
            testlabsInd.append("3")
        testlabels.append(testlabsInd.index("3"))


    path=r'D:/Pycharm/trainvoice5\test/normal_bass/'
    files = os.listdir(path)
    for i in files:
        # print(i)
        waveData = get_wav_mfcc(path+i)
        testwavs.append(waveData)
        if ("4" in testlabsInd)==False:
            testlabsInd.append("4")
        testlabels.append(testlabsInd.index("4"))

    wavs=np.array(wavs)
    labels=np.array(labels)
    testwavs=np.array(testwavs)
    testlabels=np.array(testlabels)
    return (wavs,labels),(testwavs,testlabels),(labsInd,testlabsInd)


def get_wav_mfcc(wav_path):
    import librosa
    wav, sr = librosa.load(wav_path, sr=16000)
    normalized_waveform  = wav/np.max(np.abs(wav))
    data = list(normalized_waveform)
    print(len(data))
    l.append(len(data))
    while len(data)>300000:
        del data[len(data)-1]  #删除最后一个
        del data[0]    #删除第一个
    # print(len(data))
    while len(data)<300000:
        data.append(0)
    print(len(data))

    data=np.array(data)

    # 平方之后，开平方，取正数，值的范围在  0-1  之间
    data = data ** 2
    data = data ** 0.5

    return data


if __name__ == '__main__':
    l=[]
    (wavs,labels),(testwavs,testlabels),(labsInd,testlabsInd) = create_datasets()
    print(wavs.shape,"   ",labels.shape)
    print(testwavs.shape,"   ",testlabels.shape)
    print(labsInd,"  ",testlabsInd)
    print(max(l))
    # 标签转换为独热码
    labels = keras.utils.to_categorical(labels, 2)
    testlabels = keras.utils.to_categorical(testlabels, 2)
    print(labels[0]) ## 类似 [1. 0]
    print(testlabels[0]) ## 类似 [0. 0]

    print(wavs.shape,"   ",labels.shape)
    print(testwavs.shape,"   ",testlabels.shape)

    # 构建模型
    model = Sequential()
    model.add(Dense(64, activation='relu',input_shape=(300000,)))
    #model.add(Dense(512, activation='relu'))
    #model.add(Dense(256, activation='relu'))
    model.add(Dense(32, activation='relu'))
    model.add(Dense(2, activation='softmax'))
    # [编译模型] 配置模型，损失函数采用交叉熵，优化采用Adadelta，将识别准确率作为模型评估
    model.compile(loss=keras.losses.categorical_crossentropy, optimizer=keras.optimizers.Adadelta(), metrics=['accuracy'])
    #  validation_data为验证集
    model.fit(wavs, labels, batch_size=512, epochs=300, verbose=1, validation_data=(testwavs, testlabels))

    # 开始评估模型效果 # verbose=0为不输出日志信息
    score = model.evaluate(testwavs, testlabels, verbose=0)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1]) # 准确度

    # model.save('D:/graduation design/DNN/model.h5') # 保存训练模型